<template>
  <el-input
      :value="formattedValue"
      clearable
      v-bind="$attrs"
      @input="onInput"
      @blur="onBlur"
      v-on="handleEvents"
      :size="size"
  />
</template>

<script>
export default {
  name: 'FormattedNumberInput',
  props: {
    value: {
      type: [Number, String],
      default: 0
    },
    min: {
      required: false,
      type: Number,
    },
    max: {
      required: false,
      type: Number,
    },
    size: {
      required: false,
      type: String,
    },
    handleEvents: {
      required: false,
      type: Object,
    },
  },
  computed: {
    formattedValue: {
      get() {
        // 获取时，带格式化的显示值
        return this.formatNumber(this.value);
      },
      set(newValue) {
        // 设置时，去除格式化后的值
        const numericValue = this.parseNumber(newValue);
        this.$emit('input', numericValue);
      }
    }
  },
  methods: {
    onInput(value) {
      // 处理输入，存储格式化前的值，并将格式化后的值传递上去
      this.formattedValue = value;
    },
    onBlur() {
      if (
          this.formattedValue !== null &&
          this.formattedValue !== undefined &&
          this.formattedValue !== ""
      ) {
        if (this.formattedValue > this.max) {
          this.formattedValue = this.max * 1;
        }
        if (this.formattedValue < this.min) {
          this.this.formattedValue = this.min * 1;
        }
      }
      if (this?.handleEvents?.on?.blur) {
        this?.handleEvents?.on?.blur?.();
      }
      // 失去焦点时再次确保值被正确格式化
      this.onInput(this.formattedValue);
    },
    formatNumber(value) {
      // 去除先前的所有格式化，只保留数字和小数点
      let plainNumber = value.toString().replace(/[^0-9.]/g, '');

      // 防止多个开头零除非跟随小数点
      plainNumber = plainNumber.replace(/^0+(?!\.)/, '');

      // 分离整数和小数部分
      const parts = plainNumber.split('.');
      let integerPart = parts[0];
      let decimalPart = parts.length > 1 ? '.' + parts[1] : '';

      // 格式化整数部分，加入千位分隔符
      integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');

      // 限制小数部分最多两位
      decimalPart = decimalPart.slice(0, 3);

      // 重新拼接整数和小数部分
      return integerPart + decimalPart;
    },
    parseNumber(formattedValue) {
      // 将格式化的字符串转换为数值字符串，以便于v-model双向绑定
      const parts = formattedValue.replace(/,/g, '').split('.');
      let integerPart = parts[0];
      let decimalPart = parts.length > 1 ? '.' + parts[1] : '';

      // 移除非数字字符
      integerPart = integerPart.replace(/\D/g, '');

      // 防止整数部分以零开头
      integerPart = integerPart.replace(/^0+/, '');

      // 修正只有小数的情况
      if (integerPart === '' && decimalPart.startsWith('.')) {
        integerPart = '0';
      }

      // 重新拼接整数和小数部分，返回非格式化的数值字符串
      const plainNumber = integerPart + decimalPart;

      return plainNumber;
    }
  }
};
</script>